﻿using System;
using Finance.Data;
using Finance.Data.Entities;
using System.Collections.Generic;

namespace Finance.Controllers
{
	public interface IRepayDebtDocumentController : IDocumentBaseController
	{
		IList<IDebtDocument> RetrieveDebtDocuments(DocumentType debtDocumentType);
		decimal GetDebtRemain(IDebtDocument debtDocument, DateTime date);
		decimal GetRemainRate(IDebtDocument debtDocument, DateTime date, decimal debtremain);
	}

	internal class RepayDebtDocumentController : DocumentBaseController, IRepayDebtDocumentController
	{
		public RepayDebtDocumentController(FinanceDataBase dataBase)
			:base(dataBase)
		{
		}

		public decimal GetDebtRemain(IDebtDocument debtDocument, DateTime date)
		{
			const string remainQuery = "select sum(debtamount) as remains from repaydebtdocument where debtdocumentid = @p0 and docdatetime < @p1 group by debtdocumentid";
			var data = FinanceDataBase.Sql.ExecuteScalar(remainQuery, debtDocument.Id, date);
			return data == null ? debtDocument.Amount : debtDocument.Amount - (decimal) data;
		}

		public decimal GetRemainRate(IDebtDocument debtDocument, DateTime date, decimal debtremain)
		{
			const string remainQuery = "select max(docdatetime) as lastpaymentdate from repaydebtdocument where debtdocumentid = @p0 and docdatetime < @p1 group by debtdocumentid";

            var data = FinanceDataBase.Sql.ExecuteScalar(remainQuery, debtDocument.Id, date);

			var lastDate = data != null ? (DateTime)data : debtDocument.DocDate;

			decimal rateremain = 0;

			if (debtDocument.Rate != 0)
			{
				// Different years with different daily rates
				var curDate = lastDate;
				for (int year = lastDate.Year; year < date.Year; year++)
				{
					var nextDate = new DateTime(year, 12, 31);
					var timeSpan = nextDate.Subtract(curDate);
					var usageDaysCount = (decimal)timeSpan.TotalDays;
					var dailyRate = debtDocument.Rate / (year % 4 == 0 ? 366 : 365);
					rateremain += debtremain * dailyRate * usageDaysCount;
					curDate = nextDate;
				}
				{
					var timeSpan = date.Subtract(curDate);
					var usageDaysCount = (decimal)timeSpan.TotalDays;
					var dailyRate = debtDocument.Rate / ((date.Year) % 4 == 0 ? 366 : 365);
					rateremain += debtremain * dailyRate * usageDaysCount;
				}
			}
			return rateremain;
		}

		public IList<IDebtDocument> RetrieveDebtDocuments(DocumentType debtDocumentType)
		{
			return FinanceDataBase.DebtDocuments.RetrieveDocuments(debtDocumentType);
		}
	}
}
